local sk__xingwu = fk.CreateSkill {

  name = "sk__xingwu",

  tags = {},

}

local function GetXingwu(player, src)
  if player.dead or src.dead then return end
  local room = player.room
  room:addPlayerMark(player, "@sk__xingwu", 1)
  if player:isWounded() then
    room:recover({
      who = player,
      num = 1,
      recoverBy = src,
      skillName = "sk__xingwu",
    })
  end
  if player.dead or src.dead then return end
  local skills = {}
  for _, general in ipairs(room.general_pile) do
    local g = Fk.generals[general]
    if player.gender ~= g.gender or g.gender == General.Bigender then
      table.insertTableIfNeed(skills, g:getSkillNameList())
    end
  end
  skills = table.filter(skills, function(s)
    return not player:hasSkill(s, true)
  end)
  if #skills == 0 then return end
  local skill = table.random(skills)
  local mark = player:getTableMark("sk__xingwu")
  table.insert(mark, skill)
  room:setPlayerMark(player, "sk__xingwu", mark)
  room:handleAddLoseSkills(player, skill, nil, true, false)
end
local function LoseXingwu(player, src)
  if player.dead or src.dead then return end
  local room = player.room
  room:removePlayerMark(player, "@sk__xingwu", 1)
  room:loseHp(player, 1, "sk__xingwu")
  if player.dead or src.dead then return end
  local skills = {}
  for _, g in pairs(Fk.generals) do
    if player.gender == g.gender or g.gender == General.Bigender then
      for _, s in ipairs(g:getSkillNameList()) do
        if player:hasSkill(s, true) then
          table.insertIfNeed(skills, s)
        end
      end
    end
  end
  if #skills == 0 then return end
  local skill = table.random(skills)
  local mark = player:getTableMark("sk__xingwu")
  table.removeOne(mark, skill)
  room:setPlayerMark(player, "sk__xingwu", mark)
  room:handleAddLoseSkills(player, "-" .. skill, nil, true, false)
end

sk__xingwu:addEffect(fk.GameStart, {
  name = "sk__xingwu",
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__xingwu.name) then
      return true
    end
  end,
  on_trigger = function(self, event, target, player, data)
    local n = player.hp
    self.cancel_cost = false
    for i = 1, n, 1 do
      if self.cancel_cost or not player:hasSkill(sk__xingwu.name) then break end
      self:doCost(event, target, player, n - i + 1)
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if room:askForSkillInvoke(player, sk__xingwu.name, nil, "#sk__xingwu-invoke:::" .. data) then
      return true
    end
    self.cancel_cost = true
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    for _, p in ipairs(room:getAllPlayers()) do
      if player.dead then return end
      GetXingwu(p, player)
    end
  end,
})
sk__xingwu:addEffect(fk.TurnStart, {
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__xingwu.name) and table.find(player:getCardIds("he"), function(cid, index, array)
          return Fk:getCardById(cid).suit == Card.Heart
        end) then
      return not player:isNude()
    end
  end,
  on_trigger = function(self, event, target, player, data)
    self:doCost(event, target, player, data)
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local targets = {}
    if target:getMark("@sk__xingwu") > 0 then
      targets = table.map(room:getOtherPlayers(target), Util.IdMapper)
    end
    local to, card = room:askForChooseCardAndPlayers(player, targets, 0, 1, ".|.|heart",
      "#sk__xingwu-ask::" .. target.id, sk__xingwu.name, true)
    if card and #card > 0 then
      event:setCostData(self, { to, card })
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:throwCard(event:getCostData(self)[2], sk__xingwu.name, player, player)
    if player.dead then return end
    if #event:getCostData(self)[1] > 0 then
      local to = room:getPlayerById(event:getCostData(self)[1][1])
      if not target.dead then
        LoseXingwu(target, player)
      end
      if player.dead then return end
      if not to.dead then
        GetXingwu(to, player)
      end
    elseif not target.dead then
      GetXingwu(target, player)
    end
    if player.dead or target.dead then return end
    local skills = target:getTableMark(sk__xingwu.name)
    if #skills > 0 and room:askForSkillInvoke(player, sk__xingwu.name, nil, "#sk__xingwu-switch::" .. target.id) then
      local n = #skills
      local new_skills = {}
      for _, general in ipairs(room.general_pile) do
        local g = Fk.generals[general]
        if target.gender ~= g.gender or g.gender == General.Bigender then
          table.insertTableIfNeed(new_skills, g:getSkillNameList())
        end
      end
      new_skills = table.filter(new_skills, function(s)
        return not target:hasSkill(s, true) or not table.contains(skills, s)
      end)
      if #new_skills == 0 then return end
      new_skills = table.random(new_skills, n)
      room:setPlayerMark(target, "sk__xingwu", new_skills)
      room:handleAddLoseSkills(target, "-" .. table.concat(skills, "|-") .. "|" .. table.concat(new_skills, "|"), nil,
        true, false)
    end
  end,
})

sk__xingwu:addLoseEffect(function(self, player, is_death)
  local room = player.room
  if not table.find(player.room:getOtherPlayers(player), function(p)
        return p:hasSkill("sk__xingwu", true, true)
      end) then
    for _, p in ipairs(room:getAlivePlayers()) do
      local mark = p:getTableMark(sk__xingwu.name)
      if #mark > 0 then
        room:handleAddLoseSkills(p, "-" .. table.concat(mark, "|-"), nil, true, false)
      end
      room:setPlayerMark(p, sk__xingwu.name, 0)
      room:setPlayerMark(p, "@sk__xingwu", 0)
    end
  end
end)

sk__xingwu:addEffect(fk.Deathed, {
  can_refresh = function(self, event, target, player, data)
    if target == player and not table.find(player.room:getOtherPlayers(player), function(p)
          return p:hasSkill(self, true, true)
        end) then
      return player:hasSkill(self, true, true)
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    for _, p in ipairs(room:getAlivePlayers()) do
      local mark = p:getTableMark(sk__xingwu.name)
      if #mark > 0 then
        room:handleAddLoseSkills(p, "-" .. table.concat(mark, "|-"), nil, true, false)
      end
      room:setPlayerMark(p, sk__xingwu.name, 0)
      room:setPlayerMark(p, "@sk__xingwu", 0)
    end
  end,
})

return sk__xingwu
